package io.shuttle.mbe.api

import io.shuttle.mbe.api.annotation.ChromeMinVersion
import io.shuttle.mbe.api.types.ArrayBuffer
import io.shuttle.mbe.api.types.Value1Function
import io.shuttle.mbe.api.types.Value2Function
import io.shuttle.mbe.api.types.Value3Function
import io.shuttle.mbe.api.types.Value5Function
import io.shuttle.mbe.api.types.VoidFunction

////////////////////
// Text to Speech Engine
////////////////////
/**
 * Use the `Browser.ttsEngine` API to implement a text-to-speech(TTS) engine using an extension. If your extension registers using this API, it will receive events containing an utterance to be spoken and other parameters when any extension or Chrome App uses the {@link tts} API to generate speech. Your extension can then use any available web technology to synthesize and output the speech, and send events back to the calling function to report the status.
 *
 * Permissions: "ttsEngine"
 */
interface TtsEngine {
    // Called by an engine when a language install is attempted, and when a language is uninstalled. Also called in response to a status request from a client. When a voice is installed or uninstalled, the engine should also call ttsEngine.updateVoices to register the voice.
    fun updateLanguage(
        // The install status of the language.
        status: LanguageStatus,
    )

    // Called by an engine to update its list of voices. This list overrides any voices declared in this extension's manifest.
    fun updateVoices(
        // Array of tts.TtsVoice objects representing the available voices for speech synthesis.
        voices: List<Tts.TtsVoice>
    )

    // Fired when a TTS client requests to install a new language. The engine should attempt to download and install the language, and call ttsEngine.updateLanguage with the result. On success, the engine should also call ttsEngine.updateVoices to register the newly available voices.
    // @param lang
    @ChromeMinVersion(131)
    val onInstallLanguageRequest: Events.Event<Value2Function<TtsClient, String>>

    // Fired when a TTS client requests the install status of a language.
    // @param lang
    @ChromeMinVersion(132)
    val onLanguageStatusRequest: Events.Event<Value2Function<TtsClient, String>>

    // Optional: if an engine supports the pause event, it should pause the current utterance being spoken, if any, until it receives a resume event or stop event. Note that a stop event should also clear the paused state.
    val onPause: Events.Event<VoidFunction>

    // Optional: if an engine supports the pause event, it should also support the resume event, to continue speaking the current utterance, if any. Note that a stop event should also clear the paused state.
    val onResume: Events.Event<VoidFunction>

    // Called when the user makes a call to tts.speak() and one of the voices from this extension's manifest is the first to match the options object.
    // @param event - The event from the text-to-speech engine indicating the status of this utterance.
    val onSpeak: Events.Event<Value3Function<String, SpeakOptions, Value1Function<Tts.TtsEvent>>>

    // Called when the user makes a call to tts.speak() and one of the voices from this extension's manifest is the first to match the options object. Differs from ttsEngine.onSpeak in that Chrome provides audio playback services and handles dispatching tts events.
    @ChromeMinVersion(92)
    val onSpeakWithAudioStream: Events.Event<Value5Function<String, SpeakOptions, AudioStreamOptions, Value1Function<AudioBuffer>, Value1Function<String?>>>

    // Fired when a call is made to tts.stop and this extension may be in the middle of speaking. If an extension receives a call to onStop and speech is already stopped, it should do nothing (not raise an error). If speech is in the paused state, this should cancel the paused state.
    val onStop: Events.Event<VoidFunction>

    // Fired when a TTS client indicates a language is no longer needed.
    @ChromeMinVersion(132)
    val onUninstallLanguageRequest: Events.Event<Value3Function<TtsClient, String, LanguageUninstallOptions>>

    // Parameters containing an audio buffer and associated data.
    @ChromeMinVersion(92)
    data class AudioBuffer(
        // The audio buffer from the text-to-speech engine. It should have length exactly audioStreamOptions.bufferSize and encoded as mono, at audioStreamOptions.sampleRate, and as linear pcm, 32-bit signed float i.e. the Float32Array type in javascript.
        var audioBuffer: ArrayBuffer,
        // The character index associated with this audio buffer.
        var charIndex: Number?,
        // True if this audio buffer is the last for the text being spoken.
        var isLastBuffer: Boolean?,
    )

    // Contains the audio stream format expected to be produced by an engine.
    @ChromeMinVersion(92)
    data class AudioStreamOptions(
        // The number of samples within an audio buffer.
        var bufferSize: Number,
        // The sample rate expected in an audio buffer.
        var sampleRate: Number
    )

    // The install status of a voice.
    @ChromeMinVersion(132)
    enum class LanguageInstallStatus {
        notInstalled,
        installing,
        installed,
        failed
    }

    // Install status of a language.
    @ChromeMinVersion(132)
    data class LanguageStatus(
        // Detail about installation failures. Optionally populated if the language failed to install.
        var error: String?,
        var installStatus: LanguageInstallStatus,
    )

    // Options for uninstalling a given language.
    @ChromeMinVersion(132)
    data class LanguageUninstallOptions(
        // True if the TTS client wants the language to be immediately uninstalled. The engine may choose whether or when to uninstall the language, based on this parameter and the requestor information. If false, it may use other criteria, such as recent usage, to determine when to uninstall.
        var uninstallImmediately: Boolean,
    )

    // Options specified to the tts.speak() method.
    @ChromeMinVersion(92)
    @Deprecated(
        "Deprecated since Chrome 92",
        replaceWith = ReplaceWith("Gender is deprecated and will be ignored.")
    )
    data class SpeakOptions(
        // Gender of voice for synthesized speech.
        var gender: VoiceGender?,
        // The language to be used for synthesis, in the form language-region. Examples: 'en', 'en-US', 'en-GB', 'zh-CN'.
        var lang: String?,
        // Speaking pitch between 0 and 2 inclusive, with 0 being lowest and 2 being highest. 1.0 corresponds to this voice's default pitch.
        var pitch: Number?,
        // Speaking rate relative to the default rate for this voice. 1.0 is the default rate, normally around 180 to 220 words per minute. 2.0 is twice as fast, and 0.5 is half as fast. This value is guaranteed to be between 0.1 and 10.0, inclusive. When a voice does not support this full range of rates, don't return an error. Instead, clip the rate to the range the voice supports.
        var rate: Number?,
        // The name of the voice to use for synthesis.
        var voiceName: String?,
        // Speaking volume between 0 and 1 inclusive, with 0 being lowest and 1 being highest, with a default of 1.0.
        var volume: String,
    )

    // Identifier for the client requesting status.
    @ChromeMinVersion(131)
    data class TtsClient(
        // Client making a language management request. For an extension, this is the unique extension ID. For Chrome features, this is the human-readable name of the feature.
        var id: String,
        // Type of requestor.
        var source: TtsClientSource,
    )

    @ChromeMinVersion(131)
    enum class TtsClientSource {
        chromefeature,
        extension,
    }

    @ChromeMinVersion(54)
    @Deprecated(
        "Deprecated since Chrome 70",
        replaceWith = ReplaceWith("Gender is deprecated and is ignored.")
    )
    enum class VoiceGender {
        male,
        female
    }
}